﻿module SVMLoad

open SVMTypes

let parse_instruction (i : string) : Option<Instruction> * string * string * string = //instruction,arg1,arg2,error
  let rec remove_white_spaces (i : char list) (acc : char list) (res : char list list) : char list list =
    match i with
      | [] -> res @ [acc]
      | c :: cs when c = ' '-> remove_white_spaces cs [] (res @ [acc])
      | c :: cs -> remove_white_spaces cs (acc @ [c]) res


  let token_list = remove_white_spaces (i |> list_of_string) [] [] |> List.filter(fun i -> i <> [])
  let tokens = token_list |> List.map(fun t -> string_of_list t)
  let ins = if tokens.Length > 0 then List.nth tokens 0 else ""
  let arg1 = if tokens.Length > 1 then List.nth tokens 1 else ""
  let arg2 = if tokens.Length > 2 then List.nth tokens 2 else ""

  if ins = "" then
    None,arg1,arg2,"Missing instruction"
  else
    let instruction_handler = svm.InstructionSet |> List.tryFind(fun i -> i.Symbol = ins)
    match instruction_handler with
    | None -> None,arg1,arg2,"Instruction does not exist"
    | Some handler ->
        let arg_count arg1 arg2 =
          let x = if arg1 <> "" then 1 else 0
          let y = if arg2 <> "" then 1 else 0
          x + y
        let arg_handler_count (handler : Instruction) =
          let x = if handler.Arg1.IsSome then 1 else 0
          let y = if handler.Arg2.IsSome then 1 else 0
          x + y
        if (arg_count arg1 arg2) <> (arg_handler_count handler) then
          None,arg1,arg2,("Argument count does not match instruction operands")
        else
          Some handler,arg1,arg2,""